﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using HelixToolkit;
using System.Windows.Media.Media3D;

namespace New3DDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void RoadCollection_Loaded(object sender, RoutedEventArgs e)
        {
           addLanes(sender as Roads);
            //AddDirectionLines();
        }
        void addLanes(Roads rc)
        {
            List<PointCollection> lanesCollection = new List<PointCollection>();
            //绘制道路和绿化带
            if (rc.EntryPath.LanesNumber >= 1)
            {
                lanesCollection = Helper.GetOffsetPoints(rc.EntryPath.Points, rc.RoadWidth / 2, rc.EntryPath.Points.Last(), 1);
                for (int i = 1; i <= rc.EntryPath.LanesNumber - 1; i++)
                {

                    PointCollection p = Helper.DrawRoadline(Helper.GetOffsetPoints(rc.EntryPath.Points, rc.RoadWidth / 2, rc.EntryPath.Points.Last(), 1), rc.EntryPath.LanesNumber, i);
                    List<PointCollection> tmps;
                    if (i == rc.EntryPath.ChildrenLanes1)
                    {
                        tmps = Helper.GetOffsetPoints(p, 4, p.Last(), -1);
                    }
                    else
                    {
                        tmps = Helper.GetOffsetPoints(p, rc.LaneLinePen.Thickness / 2, p.Last(), -1);
                    }
                    foreach (var item in tmps)
                    {
                        lanesCollection.Insert(lanesCollection.Count - 1, item);
                    }
                }
                for (int i = 0; i < lanesCollection.Count - 1; i += 2)
                {
                    DramDirectImage(lanes, lanesCollection[i], lanesCollection[i + 1], "直右.png");
                }
            }


            lanesCollection.Clear();
            foreach (var item in rc.ExitPaths)
            {
                PointCollection tmpp = item.Points.Clone();
                tmpp.Insert(0, rc.EntryPath.Points.Last());
                lanesCollection = Helper.GetOffsetPoints(tmpp, rc.RoadWidth / 2, rc.EntryPath.Points.Last(), 0);
                if (item.LanesNumber > 1)
                {
                    for (int i = 1; i <= item.LanesNumber - 1; i++)
                    {
                        PointCollection tmp = item.Points.Clone();
                        tmp.Insert(0, rc.EntryPath.Points.Last());
                        PointCollection p = Helper.DrawRoadline(Helper.GetOffsetPoints(tmp, rc.RoadWidth / 2, rc.EntryPath.Points.Last(), 0), item.LanesNumber, i);
                        List<PointCollection> tmps;
                        if (i == item.ChildrenLanes1)
                        {
                            tmps = Helper.GetOffsetPoints(p, 4, p.Last(), -1);
                        }
                        else
                        {
                            tmps = Helper.GetOffsetPoints(p, rc.LaneLinePen.Thickness / 2, p.Last(), -1);
                        }
                        foreach (var item2 in tmps)
                        {
                            lanesCollection.Insert(lanesCollection.Count - 1, item2);
                        }
                    }
                }
                for (int i = 0; i < lanesCollection.Count - 1; i += 2)
                {
                    DramDirectImage(lanes, lanesCollection[i], lanesCollection[i + 1], "直右.png");
                }
            }
        }

        void DramDirectImage(Canvas lanescontainer, PointCollection p1, PointCollection p2, string str)
        {
            Lane lane = new Lane();
            //foreach(var item in p2)
            //lane.PointsList.Add(p1);
            //lane.PointsList.Add(p2);
            lane.LaneDirectImage = str;
            lane.Checked += new RoutedEventHandler(lane_Checked);
            lane.UnChecked += new RoutedEventHandler(lane_UnChecked);
            lanescontainer.Children.Add(lane);

        }

        void lane_UnChecked(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("UnChecked");
        }

        void lane_Checked(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Checked");
        }

        void AddDirectionLines()
        {
        }

        private void port_MouseDown(object sender, MouseButtonEventArgs e)
        {
            //if (e.OriginalSource.GetType() == typeof(Road))
            //{
            //    Road el = e.OriginalSource as Road;

                //if (el.Tag != null && el.Tag.Equals("Roadedge"))
                //{
                    TruncatedConeVisual3D cone = new TruncatedConeVisual3D();
                    cone.BaseRadius = 0.005;
                    cone.TopRadius = 0.005;
                    cone.Height = 0.3;
                    cone.Origin = new Point3D(0, 0, 0);
                    cone.Fill = Brushes.Silver;

                    Point3D? pt = port.FindNearestPoint(e.GetPosition(port));
                    if (pt.HasValue)
                    {
                        Point3D p = pt.Value;
                        cone.Origin = p;
                        port.Children.Add(cone);
                    }
                //}
           // }
        }
    }
    class Roads : Canvas
    {
        #region 变量

        List<PointCollection> connectedLines;

        #endregion

        #region 构造

        public Roads()
        {
            //EntryPath = new RoadModel(2, 1, (PointCollection)new PointCollectionConverter().ConvertFromString("290.598290598291,0 311.111111111111,82.0512820512821 314.529914529915,119.65811965812 314.529914529915,188.034188034188 321.367521367521,218.803418803419 338.461538461538,256.410256410256 341.880341880342,297.435897435897 335.042735042735,324.786324786325 311.111111111111,352.136752136752 300.854700854701,365.811965811966 280.34188034188,379.487179487179 259.82905982906,389.74358974359 235.897435897436,400"));
            EntryPath = new RoadModel(5, 1, (PointCollection)new PointCollectionConverter().ConvertFromString("4,31 94.5,96.5 188.5,149.5 314.5,187.5 402.5,257.5 466.5,321.5 487.5,389.5"));

            ExitPaths.Add(new RoadModel(5, 2, (PointCollection)new PointCollectionConverter().ConvertFromString("705.5,402.83368 826.16667,374.16663 888.1663,330.16468 914.16594,299.4964")));
            ExitPaths.Add(new RoadModel(2, 3, (PointCollection)new PointCollectionConverter().ConvertFromString("439,465 340.5,521.5 281.5,583.5 248.5,628.5 162.5,692.5")));
            ExitPaths.Add(new RoadModel(2, 3, (PointCollection)new PointCollectionConverter().ConvertFromString("545,471 589.5,567.5 613.5,665.5 665.5,722.5 730.5,778.5")));
        }

        #endregion

        #region 注册依赖属性

        #region EntryPath

        public RoadModel EntryPath
        {
            get { return (RoadModel)GetValue(EntryPathProperty); }
            set { SetValue(EntryPathProperty, value); }
        }


        public static readonly DependencyProperty EntryPathProperty =
            DependencyProperty.Register("EntryPath", typeof(RoadModel), typeof(Roads), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));

        #endregion

        #region ExitPaths

        public List<RoadModel> ExitPaths
        {
            get { return (List<RoadModel>)GetValue(ExitPathsProperty); }
            set { SetValue(ExitPathsProperty, value); }
        }

        public static readonly DependencyProperty ExitPathsProperty =
            DependencyProperty.Register("ExitPaths", typeof(List<RoadModel>), typeof(Roads), new FrameworkPropertyMetadata(new List<RoadModel>(), FrameworkPropertyMetadataOptions.AffectsRender));

        #endregion

        #region SubgradeWith

        public int SubgradeWith
        {
            get { return (int)GetValue(SubgradeWithProperty); }
            set { SetValue(SubgradeWithProperty, value); }
        }

        public static readonly DependencyProperty SubgradeWithProperty =
            DependencyProperty.Register("SubgradeWith", typeof(int), typeof(Roads), new UIPropertyMetadata(5));

        #endregion

        #region SubgradeBrush

        public Brush SubgradeBrush
        {
            get { return (Brush)GetValue(SubgradeBrushProperty); }
            set { SetValue(SubgradeBrushProperty, value); }
        }

        public static readonly DependencyProperty SubgradeBrushProperty =
            DependencyProperty.Register("SubgradeBrush", typeof(Brush), typeof(Roads), new UIPropertyMetadata(Brushes.Orange));

        #endregion

        #region LaneLinePen

        public Pen LaneLinePen
        {
            get { return (Pen)GetValue(LaneLinePenProperty); }
            set { SetValue(LaneLinePenProperty, value); }
        }

        public static readonly DependencyProperty LaneLinePenProperty =
            DependencyProperty.Register("LaneLinePen", typeof(Pen), typeof(Roads), new UIPropertyMetadata(Helper.CreatePen((Brush)new BrushConverter().ConvertFromString("#30FFFFFF"), Helper.CreateDashStyle("4,4"), 1)));

        #endregion

        #region RoadWidth

        public int RoadWidth
        {
            get { return (int)GetValue(RoadWidthProperty); }
            set { SetValue(RoadWidthProperty, value); }
        }

        public static readonly DependencyProperty RoadWidthProperty =
            DependencyProperty.Register("RoadWidth", typeof(int), typeof(Roads), new UIPropertyMetadata(60));

        #endregion

        #region RoadBrush

        public Brush RoadBrush
        {
            get { return (Brush)GetValue(RoadBrushProperty); }
            set { SetValue(RoadBrushProperty, value); }
        }

        public static readonly DependencyProperty RoadBrushProperty =
            DependencyProperty.Register("RoadBrush", typeof(Brush), typeof(Roads), new UIPropertyMetadata(new ImageBrush() { ImageSource = (ImageSource)new ImageSourceConverter().ConvertFromString("road.jpg") }));

        #endregion

        #endregion

        #region 重写

        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);
            connectedLines = new List<PointCollection>();
            PointCollection connectedLine = new PointCollection();
            List<PointCollection> allSubgrade = new List<PointCollection>();
            connectedLine = EntryPath.Points.Clone();
            foreach (var road in ExitPaths)
            {
                connectedLine = EntryPath.Points.Clone();
                foreach (var item in road.Points)
                {
                    connectedLine.Add(item);
                }
                connectedLines.Add(connectedLine);
                List<PointCollection> listPointColl = Helper.GetOffsetPoints(connectedLine, RoadWidth / 2, EntryPath.Points.Last());
                foreach (var item in listPointColl)
                {
                    allSubgrade.Add(item);
                }
            }

            //绘制路基
            foreach (var item in allSubgrade)
            {
                Helper.Draw(dc, Brushes.Transparent, item, Helper.CreatePen(SubgradeBrush, null, SubgradeWith));
            }


            //绘制路面
            for (int i = 0; i < allSubgrade.Count - 1; i += 2)
            {
                Helper.Draw(dc, RoadBrush,
                    Helper.ConcatReversePoints(allSubgrade[i], allSubgrade[i + 1]), Helper.CreatePen(Brushes.Transparent, null));
            }


            ////绘制道路和绿化带
            //if (EntryPath.LanesNumber > 1)
            //{
            //    for (int i = 1; i <= EntryPath.LanesNumber - 1; i++)
            //    {

            //        PointCollection p = Helper.DrawRoadline(Helper.GetOffsetPoints(EntryPath.Points, RoadWidth / 2, EntryPath.Points.Last(), 1), EntryPath.LanesNumber, i);
            //        if (i == EntryPath.ChildrenLanes1)
            //        {
            //            Helper.DrawIsolationBelt(dc, p, EntryPath.Points.Last());
            //        }
            //        else
            //        {
            //            Helper.Draw(dc, Brushes.Transparent, p, LaneLinePen);
            //        }
            //    }
            //}
            //foreach (var item in ExitPaths)
            //{
            //    if (item.LanesNumber > 1)
            //    {
            //        for (int i = 1; i <= item.LanesNumber - 1; i++)
            //        {
            //            PointCollection tmp = item.Points.Clone();
            //            tmp.Insert(0, EntryPath.Points.Last());
            //            PointCollection p = Helper.DrawRoadline(Helper.GetOffsetPoints(tmp, RoadWidth / 2, EntryPath.Points.Last(), 0), item.LanesNumber, i);
            //            if (i == item.ChildrenLanes1)
            //            {
            //                Helper.DrawIsolationBelt(dc, p, EntryPath.Points.Last());
            //            }
            //            else
            //            {
            //                Helper.Draw(dc, Brushes.Transparent, p, LaneLinePen);
            //            }
            //        }
            //    }
            //}
        }

        #endregion

        internal class RoadModel
        {
            public RoadModel(int number1, int number2, PointCollection points)
            {
                ChildrenLanes1 = number1;
                ChildrenLanes2 = number2;
                LanesNumber = number1 + number2;
                Points = points;
            }

            public int LanesNumber { get; private set; }

            public PointCollection Points { get; set; }

            public int ChildrenLanes1 { get; set; }
            public int ChildrenLanes2 { get; set; }

        }
    }
}
